gl renderer: Expand matrix metadata extraction
authorTimm Bäder <tbaeder@redhat.com>
Wed, 28 Nov 2018 08:30:27 +0000 (09:30 +0100)
committerTimm Bäder <mail@baedert.org>
Thu, 29 Nov 2018 07:23:42 +0000 (08:23 +0100)
Instead of getting the translation x/y everytime we use the modelview,
get it once, when extracting the metadata. Do the same with the scale.
And save if the matrix is "simple" at all, i.e. if it only consists of a
translation and/or scale. This will be helpful later when we start
drawing transformed nodes on textures.

gsk/gl/gskglrenderops.c
gsk/gl/gskglrenderopsprivate.h

index f0ef2f633e70f6d2e76e77ed6e9de81b2f2cc397..1ac8f8866eb90e99c8a3edd57c66810971b025ff 100644 (file)
@@ -7,7 +7,6 @@ ops_finish (RenderOpBuilder *builder)
     g_array_free (builder->mv_stack, TRUE);
 }
 
-
 static inline void
 rgba_to_float (const GdkRGBA *c,
                float         *f)
@@ -28,38 +27,9 @@ ops_get_scale (const RenderOpBuilder *builder)
 
   head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
 
-  return head->metadata.scale;
-}
-
-static inline gboolean
-matrix_is_only_translation (const graphene_matrix_t *mat)
-{
-  graphene_vec4_t row1;
-  graphene_vec4_t row2;
-  graphene_vec4_t row3;
-  graphene_vec4_t row;
-
-  graphene_vec4_init (&row1, 1, 0, 0, 0);
-  graphene_vec4_init (&row2, 0, 1, 0, 0);
-  graphene_vec4_init (&row3, 0, 0, 1, 0);
-
-  graphene_matrix_get_row (mat, 0, &row);
-  if (!graphene_vec4_equal (&row1, &row))
-    return FALSE;
-
-  graphene_matrix_get_row (mat, 1, &row);
-  if (!graphene_vec4_equal (&row2, &row))
-    return FALSE;
-
-  graphene_matrix_get_row (mat, 2, &row);
-  if (!graphene_vec4_equal (&row3, &row))
-    return FALSE;
-
-  graphene_matrix_get_row (mat, 3, &row);
-  if (graphene_vec4_get_w (&row) != 1)
-    return FALSE;
-
-  return TRUE;
+  /* TODO: Use two separate values */
+  return MAX (head->metadata.scale_x,
+              head->metadata.scale_y);
 }
 
 static void
@@ -69,10 +39,9 @@ extract_matrix_metadata (const graphene_matrix_t *m,
   graphene_vec3_t col1;
   graphene_vec3_t col2;
 
-  /* Is this matrix JUST a translation? */
-  md->is_only_translation = matrix_is_only_translation (m);
-
-  /* TODO: We should probably split this up into two values... */
+  /* Translate */
+  md->translate_x = graphene_matrix_get_value (m, 3, 0);
+  md->translate_y = graphene_matrix_get_value (m, 3, 1);
 
   /* Scale */
   graphene_vec3_init (&col1,
@@ -85,9 +54,36 @@ extract_matrix_metadata (const graphene_matrix_t *m,
                       graphene_matrix_get_value (m, 1, 1),
                       graphene_matrix_get_value (m, 2, 1));
 
-  md->scale = MAX (graphene_vec3_length (&col1),
-                   graphene_vec3_length (&col2));
-
+  md->scale_x = graphene_vec3_length (&col1);
+  md->scale_y = graphene_vec3_length (&col2);
+
+  /* A simple matrix (in our case) is one that doesn't do anything but scale
+   * and/or translate.
+   *
+   * For orher matrices, we fall back to offscreen drawing.
+   */
+  md->simple = TRUE;
+  {
+    static const guchar check_zero[4][4] = {
+      { 0, 1, 0, 1 },        /* If any of the values marked as '1' here is non-zero, */
+      { 1, 0, 0, 1 },        /* We have to resort to offscreen drawing later on. */
+      { 1, 1, 0, 1 },
+      { 0, 0, 0, 0 },
+    };
+    int x, y;
+
+    for (x = 0; x < 4; x ++)
+      for (y = 0; y < 4; y ++)
+          if (check_zero[y][x] &&
+              graphene_matrix_get_value (m, y, x) != 0.0f)
+            {
+              md->simple = FALSE;
+              goto out;
+            }
+  }
+
+out:
+  md->only_translation = (md->simple && md->scale_x == 0 && md->scale_y == 0);
 }
 
 
@@ -103,14 +99,12 @@ ops_transform_bounds_modelview (const RenderOpBuilder *builder,
 
   head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
 
-  if (head->metadata.is_only_translation)
+  if (head->metadata.only_translation)
     {
-      graphene_vec4_t row4;
-
-      /* TODO: We could do the get_row here only once, when setting the new modelview matrix. */
-      graphene_matrix_get_row (builder->current_modelview, 3, &row4);
       *dst = *src;
-      graphene_rect_offset (dst, graphene_vec4_get_x (&row4), graphene_vec4_get_y (&row4));
+      graphene_rect_offset (dst,
+                            head->metadata.translate_x,
+                            head->metadata.translate_y);
     }
   else
     {
index 18a47342574966489bf6846641eeb4fb8aa8720a..7b0b1f824f86f8b0ff9b8be8df9a60f66768b419 100644 (file)
 
 typedef struct
 {
-  guint is_only_translation : 1;
-  float scale;
+  float translate_x;
+  float translate_y;
+  float scale_x;
+  float scale_y;
+
+  guint simple : 1;
+  guint only_translation : 1;
 } OpsMatrixMetadata;
 
 typedef struct